home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Magnum One
/
Magnum One (Mid-American Digital) (Disc Manufacturing).iso
/
d11
/
vmoire14.arc
/
VGA.INC
< prev
next >
Wrap
Text File
|
1991-04-21
|
28KB
|
684 lines
;
; VGA.INC
;
; declares the VGA-specific procedures used by VGAMoire.
;
MaxBound equ 8 ;velocity variables are in range [-MaxBound,-MinBound] || [MinBound,MaxBound]
MinBound equ 3
BytesPerLine equ 80 ;bytes in one horizontal line
VideoBufferSeg equ 0a000h ;segment of video buffer
CGenRAMSeg equ 0a000h ;segment of character generator RAM
TextBufferSeg equ 0b000h ;text memory starts here
OriginOffset equ 0 ;byte offset of (0,0)
ByteOffsetShift equ 3 ;used to convert pixels to byte offset
RMWbits equ 0 ;value for Data Rotate/Func Select reg
MaxY dw 479 ;maximum y-coordinate
MaxX dw 639 ;maximum x-coordinate
refresh proc near ;enable/disable screen refresh
; call with al = 00h --> enable refresh
; = 01h --> disable refresh
mov ah,12h
mov bl,36h
int 10h
ret
refresh endp
getDAC proc near ;read video DAC color registers
; ARGS: al = video DAC color register to start at
; cx = 3 * (number of registers to read)
; es:di -> where to store registers read
mov dx,03c7h ;set video DAC read
cli ;disable interrupts
out dx,al
mov dx,03c9h ;read video DAC color registers
@@vDACget:
in al,dx ;get color register value
and al,3fh ;mask off the upper 2 bits
stosb ;store it
loop @@vDACget ;loop until done
sti ;enable interrupts
ret
getDAC endp
setDAC proc near ;set video DAC color registers
; ARGS: al = video DAC color register to start at
; cx = 3 * (number of registers to write)
; ds:si -> where to get values to write
mov dx,03c8h ;set video DAC write
cli ;disable interrupts
out dx,al
mov dx,03c9h ;write video DAC color registers
@@vDACset:
lodsb ;get stored video DAC color values
out dx,al ;write value to video DAC color reg
loop @@vDACset ;loop until done
sti ;enable interrupts
ret
setDAC endp
SETCOLORS macro
mov si,offset blackcolor ;where to get video DAC color defs from
mov al,0 ;set video DAC color regs 0 thru 5
mov cx,6*3
call setDAC
mov al,20 ;set video DAC color reg 20
mov cx,1*3
call setDAC
mov al,7 ;set video DAC color reg 7
mov cx,1*3
call setDAC
mov al,56 ;set video DAC color regs 56 thru 63
mov cx,8*3
call setDAC
endm
CGenModeSet proc near
push si
push ds
push cs ;set up addressibility for our data
pop ds
; Program the Sequencer
cli ;disable interrupts
mov dx,3c4h ;Sequencer port address
mov si,offset @@SeqParms
mov cx,4
@@L01:
lodsw ;ah=val. for Seq. reg., al=reg. num.
out dx,ax
loop @@L01
sti ;enable interrupts
; Program the Graphics Controller
mov dl,0ceh ;dx=3ceh (Graphics Controller port address)
mov si,offset @@GCParms
mov cx,3
@@L02:
lodsw
out dx,ax
loop @@L02
pop ds
pop si
ret
@@SeqParms dw 0100h ;synchronous reset
dw 0402h ;CPU writes only to map 2
dw 0704h ;sequential addressing
dw 0300h ;clear synchronous reset
@@GCParms dw 0204h ;select map 2 for CPU reads
dw 0005h ;disable odd-even addressing
dw 0006h ;map starts at A000:0000
CGenModeSet endp
CGenModeClear proc near
push si
push ds
push cs ;set up addressibility for our data
pop ds
; Program the Sequencer
cli ;disable interrupts
mov dx,3c4h ;Sequencer port address
mov si,offset @@SeqParms
mov cx,4
@@L01:
lodsw ;ah=val. for Seq. reg., al=reg. num.
out dx,ax
loop @@L01
sti ;enable interrupts
; Program the Graphics Controller
mov dl,0ceh ;dx=3ceh (Graphics Controller port address)
mov si,offset @@GCParms
mov cx,3
@@L02:
lodsw
out dx,ax
loop @@L02
mov ah,0fh ;get video mode
int 10h
cmp al,7
jne @@L03
mov ax,0806h ;program Graphics Controller
out dx,ax ; to start map at B000:0000
@@L03:
pop ds
pop si
ret
@@SeqParms dw 0100h ;synchronous reset
dw 0302h ;CPU writes to maps 0 and 1
dw 0304h ;odd-even addressing
dw 0300h ;clear synchronous reset
@@GCParms dw 0004h ;select map 0 for CPU reads
dw 1005h ;enable odd-even addressing
dw 0e06h ;map starts at B800:0000
CGenModeClear endp
PixelAddr10 proc near ;gets address of pixel
; ARGS: AX = y-coordinate
; BX = x-coordinate
; RETS: AH = bit mask
; BX = byte offset in buffer
; CL = number of bits to shift left
; ES = video buffer segment
mov cl,bl ;cl = low-order byte of x
push dx ;preserve dx
mov dx,BytesPerLine ;ax = y*BytesPerLine
mul dx
pop dx
shr bx,1
shr bx,1
shr bx,1 ;bx = x/8
add bx,ax ;bx = y*BytesPerLine + x/8
; add bx,OriginOffset ;bx = byte offset in video buffer
mov ax,VideoBufferSeg
mov es,ax ;es:bx = byte address of pixel
and cl,7 ;cl = x&7
xor cl,7 ;cl = number of bits to shift left
mov ah,1 ;ah = unshifted bit mask
ret
PixelAddr10 endp
Line10 proc near
ARG ARGx1, ARGy1, ARGx2, ARGy2, ARGn:BYTE = ARGS ;declare arguments
LOCAL VARvertincr, VARincr1, VARincr2, VARroutine = VARS ;declare local variables
push bp
mov bp,sp ;save stack context
sub sp,VARS ;allocate space for local variables
push si
push di
; configure the Graphics Controller
mov dx,3ceh ;dx = Graphics Controller port addr
mov ah,[ARGn] ;ah = pixel value
xor al,al ;al = Set/Reset Register number
out dx,ax
mov ax,0f01h ;ah = 1111b (bit plane mask for Enable Set/Reset)
out dx,ax ;al = Enable Set/Reset Register #
mov ah,RMWbits ;bits 3 and 4 of ah = function
mov al,3 ;al = Data Rotate/Func Select reg #
out dx,ax
; check for vertical line
mov si,BytesPerLine ;increment for video buffer
mov cx,[ARGx2]
sub cx,[ARGx1] ;cx = x2-x1
jz VertLine10 ;jump if vertical line
; force x1<x2
jns @@L01 ;jump if x2>x1
neg cx ;cx = x1-x2
mov bx,[ARGx2] ;exchange x1 and x2
xchg bx,[ARGx1]
mov [ARGx2],bx
mov bx,[ARGy2] ;exchange y1 and y2 [check first??]
xchg bx,[ARGy1] ;these are the two lines i missed
mov [ARGy2],bx
; calculate dy = ABS(y2-y1)
@@L01:
mov bx,[ARGy2]
sub bx,[ARGy1] ;bx = y2-y1
jz HorizLine10 ;jump if horizontal line
jns @@L03 ;jump if slope is positive
neg bx ;bx = y1-y2
neg si ;negate increment for buffer interleave
; select appropriate routine for slope of line
@@L03:
mov [VARvertincr],si ;save vertical increment
mov [VARroutine],offset LoSlopeLine10
cmp bx,cx
jle @@L04 ;jump if dy<=dx (slope<=1)
mov [VARroutine],offset HiSlopeLine10
xchg bx,cx ;exchange dy and dx
; calculate initial decision variable and increments
@@L04:
shl bx,1 ;bx = 2*dy
mov [VARincr1],bx ;incr1 = 2*dy
sub bx,cx
mov si,bx ;si = 2*dy-dx
sub bx,cx
mov [VARincr2],bx ;incr2 = 2*(dy-dx)
; calculate first pixel address
push cx ;preserve register
mov ax,[ARGy1] ;AX = y
mov bx,[ARGx1] ;BX = x
call PixelAddr10 ;ah = bit mask
;es:bx -> buffer
;cl = # bits to shift left
mov di,bx ;es:di -> buffer
shl ah,cl ;ah = bit mask in proper position
mov bl,ah ;ah,bl = bit mask
mov al,8 ;al = Bit Mask Register number
pop cx ;restore register
inc cx ;cx = # of pixels to draw
jmp [VARroutine] ;jump to appropriate routine for slope
VertLine10: ;routine for vertical lines
mov ax,[ARGy1] ;ax = y1
mov bx,[ARGy2] ;bx = y2
mov cx,bx
sub cx,ax ;cx = dy
jge @@L31 ;jump if dy>=0
neg cx ;force dy>=0
mov ax,bx ;ax = y2
@@L31:
inc cx ;cx = # of pixels to draw
mov bx,[ARGx1] ;bx = x
push cx ;preserve register
call PixelAddr10 ;ah = bit mask
;es:bx -> buffer
;cl = # bits to shift left
; set up Graphics Controller
shl ah,cl ;ah = bit mask in proper position
mov al,8 ;al = Bit Mask reg number
out dx,ax
pop cx ;restore register
; draw the line
@@L32:
or es:[bx],al ;set pixel
add bx,si ;increment to next line
loop @@L32
jmp Lexit
HorizLine10: ;routine for horizontal lines (slope=0)
push ds ;preserve ds
mov ax,[ARGy1]
mov bx,[ARGx1]
call PixelAddr10 ;ah = bit mask
;es:bx -> buffer
;cl = # bits to shift left
mov di,bx ;es:di -> buffer
mov dh,ah ;dh = unshifted bit mask for leftmost byte
not dh
shl dh,cl ;dh = reverse bit make for first byte
not dh ;dh = bit mask for first byte
mov cx,[ARGx2]
and cl,7
xor cl,7 ;cl = number of bits to shift left
mov dl,0ffh ;dl = unshifted bit mask for rightmost byte
shl dl,cl ;dl = bit mask for last byte
; determine byte offset of first and last pixel in the line
mov ax,[ARGx2] ;ax = x2
mov bx,[ARGx1] ;bx = x1
mov cl,ByteOffsetShift ;number of bits to shift to convert pixels to bytes
shr ax,cl ;ax = byte offset of x2
shr bx,cl ;bx = byte offset of x1
mov cx,ax
sub cx,bx ;cx = (# bytes in line) -1
; get Graphics Controller port address into dx
mov bx,dx ;bh = bit mask for first byte
;bl = bit mask for last byte
mov dx,3ceh ;dx = Graphics Controller port
mov al,8 ;al = Bit Mask Register number
; make video buffer addressable through ds:si
push es
pop ds
mov si,di ;ds:si -> video buffer
; set pixels in leftmost byte of the line
or bh,bh
js @@L43 ;jump if byte-aligned (x1 is leftmost pixel in byte)
or cx,cx
jnz @@L42 ;jump if more than one byte in the line
and bl,bh ;bl = bit mask for the line
jmp short @@L44
@@L42:
mov ah,bh ;ah = bit mask for 1st byte
out dx,ax ;update Graphics Controller
movsb ;update bit planes
dec cx
; use a fast 8086 machine instruction to draw the remainder of the line
@@L43:
mov ah,11111111b ;ah = bit mask
out dx,ax ;update Bit Mask Register
rep movsb ;update all pixels in the line
; set pixels in the rightmost byte of the line
@@L44:
mov ah,bl ;ah = bit mask for last byte
out dx,ax ;update Graphics Controller
movsb ;update bit planes
pop ds ;restore ds
jmp short Lexit
;es:di -> video buffer
;al = Bit Mask Register number
;bl = bit mask for 1st pixel
;cx = # of pixels to draw
;dx = Graphics Controller port addr
;si = decision variable
LoSlopeLine10: ;routine for dy>=dx (slope<=1)
@@L10:
mov ah,bl ;ah = bit mask for next pixel
@@L11:
or ah,bl ;mask current pixel position
ror bl,1 ;rotate pixel value
jc @@L14 ;jump if bit mask rotated to leftmost position
; bit mask not shifted out
or si,si ;test sign of d
jns @@L12 ;jump if d>=0
add si,[VARincr1] ;d = d+incr1
loop @@L11
out dx,ax ;update Bit Mask Register
or es:[di],al ;set remaining pixel(s)
jmp short Lexit
@@L12:
add si,[VARincr2] ;d = d+incr2
out dx,ax ;update Bit Mask Register
or es:[di],al ;update bit planes
add di,[VARvertincr] ;increment y
loop @@L10
jmp short Lexit
; bit mask shifted out
@@L14:
out dx,ax ;update Bit Mask Register ...
or es:[di],al ;update bit planes
inc di ;increment x
or si,si ;test sign of d
jns @@L15 ;jump if non-negative
add si,[VARincr1] ;d = d+incr1
loop @@L10
jmp short Lexit
@@L15:
add si,[VARincr2] ;d = d+incr2
add di,[VARvertincr] ;vertical increment
loop @@L10
jmp short Lexit
;es:di -> video buffer
;ah = bit mask for 1st pixel
;al = Bit Mask Register number
;cx = # of pixels to draw
;dx = Graphics Controller port addr
;si = decision variable
HiSlopeLine10: ;routine for dy<dx (slope>1)
mov bx,[VARvertincr] ;bx = y-increment
@@L21:
out dx,ax ;update Bit Mask Register
or es:[di],al ;update bit planes
add di,bx ;increment y
@@L22:
or si,si ;test sign of d
jns @@L23 ;jump if d>=0
add si,[VARincr1] ;d = d+incr1
loop @@L21
jmp short Lexit
@@L23:
add si,[VARincr2] ;d = d+incr2
ror ah,1 ;rotate bit mask
adc di,0 ;increment di if when mask rotated to leftmost pixel position
loop @@L21
; restore default Graphics Controller state and return to caller
Lexit: xor ax,ax ;ah = 0, al = 0
out dx,ax ;restore Set/Reset Register
inc ax ;ah = 0, al = 1
out dx,ax ;restore Enable Set/Reset Register
mov al,3 ;ah = 0, al = 3
out dx,ax ;al = Data Rotate/Func Select reg #
mov ax,0ff08h ;ah = 11111111b, al = 8
out dx,ax ;restore Bit Mask Register
pop di ;restore registers and return
pop si
mov sp,bp ;deallocate local variables
pop bp ;restore stack context
ret ARGS ;return and pop arguments from stack
Line10 endp
copyfont proc near ;al=0 to restore, 1 to save
cmp [fontblocks],0 ;do we save any character generator RAM
jnz @@yesfont
jmp @@nofont
@@yesfont:
push ds ;save ds
push ax
mov ax,4400h ;map logical EMS pages to physical page frame
mov cl,[fontblocks] ;number of blocks of font RAM to save
xor ch,ch
inc cl ;round up and
shr cl,1 ; convert to num. of EMS pages needed
xor bh,bh
mov bl,[useEMS] ;al=logical page to start at
@@maploop:
push ax ;map the EMS pages
push bx
mov dx,[EMShandle]
int 67h
or ah,ah
jnz @@maperror ;@@maperror cleans up and returns with carry set, to indicate a failure
pop bx
pop ax
inc bl
inc al
loop @@maploop
mov bx,[storetext]
xor dx,dx
pop ax
or al,al ;copy from or to font RAM
jz @@restore
mov es,bx ;make pointer to save area
mov di,dx
mov bx,CGenRAMSeg ;points to character RAM on map 2
mov ds,bx
xor si,si
jmp @@copyfont
@@restore: ;copy font RAM back
mov ds,bx
mov si,dx
mov bx,CGenRAMSeg ;points to character RAM on map 2
mov es,bx
xor di,di
@@copyfont:
call CGenModeSet ;program VGA card to allow r/w access to character RAM
mov ah,cs:[fontblocks] ;number of blocks of font RAM to copy
xor al,al
mov cl,4
shl ah,cl
mov cx,ax
rep movsw ;copy font RAM
call CGenModeClear ;program VGA card back to normal
pop ds ;restore ds
@@nofont:
clc
ret
@@maperror:
pop bx ;pop saved registers
pop ax
pop ax
pop ds
call freebuf
stc
ret
copyfont endp
loadfont proc ;loads a ROM font using a best-fit algorithm
push es
mov es,[keybuff] ;set es=0000:0000
mov ax,word ptr es:[485h]
cmp ax,8 ;8x8 font?
ja @@8x14
mov al,02h ; if font <= 8x8, load 8x8
jmp @@loadfont
@@8x14:
cmp ax,14 ;8x14 font?
ja @@8x16
mov al,01h ; if font <= 8x14, load 8x14
jmp @@loadfont
@@8x16:
mov al,04h ; if font > 8x14, load 8x16
@@loadfont:
mov ah,11h ;load ROM font (al and bl are already set appropriately)
int 10h
pop es
ret
loadfont endp
copytext proc near ;copy text from buffer to buffer
push ax
or al,al
jnz @@store
mov ax,1c02h ;restore video state
mov cx,7 ;all video info
mov bx,[storetext]
mov es,bx
mov bx,[buffersize] ;es:bx -> buffer for video state
add bx,[mousesize] ;index past the mouse state save buffer
push bx ;store offset temporarily
int 10h
mov ah,1bh
xor bx,bx ; (don't need to set es because it retains its value through the previous int)
pop di ;reuse video state buffer to get some video info
int 10h ;get some video info
mov bl,byte ptr es:[2bh]
cmp [fontblocks],bl ;did we save the primary font block?
jg @@secondary ;if so, check about the secondary font block
call loadfont ;load the appropriate ROM font
@@secondary:
cmp bl,byte ptr es:[2ch] ;if primary and secondary font blocks are the same
je @@store ; then skip processing the block a second time
mov bl,byte ptr es:[2ch]
cmp fontblocks,bl ;did we save the secondary font block?
jg @@store ;if so, we're all set
call loadfont ;load the appropriate ROM font
@@store:
pop ax
push ds ;save ds
push [buffersize] ;save video text buffer size
push [textbuff] ;save textbuff
mov bx,[storetext] ;buffer is at bx:dx
xor dx,dx
or al,al ;copy in which direction
jz @@restore
push cs ;set es = cs
pop es
pop ds ;ds = textbuff
xor si,si
mov es,bx ;into bx:dx = es:di
mov di,dx
jmp @@copytext
@@restore:
push cs ;set ds = cs
pop ds
pop es ;es = textbuff
xor di,di
mov ds,bx ;copy this buffer
mov si,dx
@@copytext:
pop cx ;cx = buffersize
rep movsb ;copy text
pop ds ;restore ds
or al,al
jz @@done
mov ax,1c01h ;save video state
mov cx,7 ;all video info
mov bx,[storetext]
mov es,bx
mov bx,[buffersize] ;es:bx -> buffer for video state
add bx,[mousesize] ;index past the mouse state save buffer
int 10h
@@done:
ret
copytext endp
STORE macro
mov al,1 ;set al = 1 to
call copytext ; copy text from video area to our buffer
mov al,1 ;set al = 1 to
call copyfont ; copy font RAM to our buffer
jc @@gofail
endm
SETMODE macro
mov ax,12h ;set graphics mode (VGA 640x480 16 color)
int 10h ; (seems to work w/EGA, too...)
endm
RESTORE macro
; try to restore from EMS, first, if [fontblocks] is set, but if not possible, do it the old-fashioned way
xor al,al ;set al = 0 to signal restore
call copyfont
call getbuf
jc @@fail ;if couldn't access buffer, we can't do anything more
xor al,al ;set al = 0 to signal restore
call copytext
push es
mov ax,17h ;restore mouse state
push [storetext] ;get segment of save buffer
pop es
mov dx,[buffersize] ;offset past stored video screen
int 33h
pop es
mov ax,1 ;show pointer (only actually does if it was showing before)
int 33h
call freebuf ;restore EMS state if used
endm
public ARGS
;public ARGn
;public ARGx1
;public ARGx2
;public ARGy1
;public ARGy2
public ByteOffsetShift
public BytesPerLine
public CGenModeClear
public CGenModeSet
public CGenRAMSeg
public HiSlopeLine10
public HorizLine10
public Lexit
public Line10
public LoSlopeLine10
public MaxBound
public MaxX
public MaxY
public MinBound
public OriginOffset
public PixelAddr10
public RMWbits
public TextBufferSeg
;public VARincr1
;public VARincr2
;public VARroutine
;public VARvertincr
public VertLine10
public VideoBufferSeg
public copyfont
public copytext
public getDAC
public VARS
public loadfont
public refresh
public setDAC
;______ eof ________________________________________________________ eof ______